package p2pcdnsim.cdn;

import p2pcdnsim.exception.PortAlreadyInUseException;
import p2pcdnsim.network.ApplicationProcess;
import p2pcdnsim.network.ServerSocket;
import p2pcdnsim.network.Socket;
import desmoj.core.simulator.Model;
import desmoj.core.simulator.SimTime;

public class FileSurrogate extends Surrogate {

	private static final int HTTP_PORT = 80;
	private CachingStrategy<ObjectContent> cache;
	
	public FileSurrogate(Model owner, String name, CDN cdn, CachingStrategy<ObjectContent> cache) {
		super(owner, name, cdn);
		this.cache = cache;
	}

	@Override
	protected void run() {
		ServerSocket server = null;
		try {
			server = this.createServerSocket(HTTP_PORT );
		} catch (PortAlreadyInUseException e) {
			throw new RuntimeException(e);
		}
		
		while(true) {
			System.out.println("["+this.currentTime()+"] Server: Waiting for a connection...");
			Socket socket = server.accept();
			SurrogateRoutine routine =  new SurrogateRoutine(this.currentModel(),this.getName(),cache, socket);
			routine.activate(new SimTime(0.0));
		}
	}

	private class SurrogateRoutine extends ApplicationProcess {

		Socket socket;
		CachingStrategy<ObjectContent> cache;
		
		public SurrogateRoutine(Model owner, String name, CachingStrategy<ObjectContent> cache, Socket socket) {
			super(owner, name);
			this.socket = socket;
			this.cache = cache;
		}
		
		@Override
		protected void run() {
			System.out.println("["+this.currentTime()+"] Server: Accepted a connection: "+socket);
			ObjectRequest request = (ObjectRequest)socket.receiveMessage();
			ObjectContent content = cache.retrieveObject(request.getObjectId(),this.currentTime());
			if(content == null) {
				content = getFromOriginServer(request.getObjectId());
				if(cache.insertObject(content, this.currentTime() )) {
					System.out.println("Object inserted.");
				} else {
					System.out.println("Object not inserted.");
				}
			}

			socket.sendMessage(content);
			socket.close();
		}

		private ObjectContent getFromOriginServer(long objectId) {
			// TODO establish a connection to the origin server and get content
			return null;
		}
		
	}
}
